package com.qinglei.recoup.hmp.controller;

import com.qinglei.recoup.common.utils.HttpXmlClient;
import com.qinglei.recoup.hmp.pojo.event.WechatMpSubscribeEvent;
import com.qinglei.recoup.hmp.pojo.vo.HmpWeChatCheckValidParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.XmlUtils;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * <p>微信公众号控制器</p>
 *
 * @author shiyupeng
 * @date 2022/1/8
 */
@Api(tags = "微信公众号控制器")
@Slf4j
@Validated
@RestController
@RequestMapping("hmp/wechat")
public class HmpWeChatController {

    public static final String TOKEN = "kXs9k5rCdFvsXFGL";

    @Value("${wx.appId}")
    private String appId;
    @Value("${wx.appSecret}")
    private String appSecret;

    @Autowired
    private ApplicationContext applicationContext;

    @ApiOperation(value = "微信公众号服务端校验接口")
    @GetMapping("/callback")
    public String checkValid(HmpWeChatCheckValidParam param) {
        log.info("wechat checkValid param:{}", param);
        List<String> signOriArr = Arrays.asList(TOKEN, param.getTimestamp(), param.getNonce());
        log.info("wechat checkValid signArr:{}", signOriArr);
        signOriArr.sort(Comparator.naturalOrder());
        log.info("wechat checkValid signArr sort:{}", signOriArr);
        String signOriStr = String.join("", signOriArr);
        log.info("wechat checkValid signOriStr:{}", signOriStr);
        String signStr = "";
        try {
            // 获取指定摘要算法的messageDigest对象 此处的sha代表sha1
            MessageDigest messageDigest = MessageDigest.getInstance("SHA");
            // 调用digest方法，进行加密操作
            byte[] cipherBytes = messageDigest.digest(signOriStr.getBytes());
            signStr = Hex.encodeHexString(cipherBytes);
            log.info("wechat checkValid signStr:{}", signStr);
        } catch (NoSuchAlgorithmException e) {
            log.error("wechat checkValid create sign error,param:{}", param, e);
        }
        if (signStr.equals(param.getSignature())) {
            log.info("wechat checkValid check Signature success!");
            return param.getEchostr();
        }
        log.info("wechat checkValid check Signature failed!");
        return "failed";
    }

    @ApiOperation(value = "微信公众号服务端回调接口")
    @PostMapping("/callback")
    public void procCallback(HttpServletRequest request) {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
            String line = "";
            StringBuffer buffer = new StringBuffer();
            while ((line = br.readLine()) != null) {
                buffer.append(line);
            }
            String notifyXml = buffer.toString();
//            log.info("wechat procCallback xml:{}", notifyXml);

            Map<String, Object> xmlMap = XmlUtils.xml2Map(notifyXml);
            log.info("wechat procCallback xmlMap:{}", xmlMap);

            // 发布事件
            String msgType = (String) xmlMap.get("MsgType");
            if (msgType.equals("event")) {
                String event = (String) xmlMap.get("Event");
                if (event.equals("subscribe") || event.equals("unsubscribe")) {
                    WechatMpSubscribeEvent wechatMpSubscribeEvent = new WechatMpSubscribeEvent(applicationContext);
                    wechatMpSubscribeEvent.setEvent(event);
                    wechatMpSubscribeEvent.setFromUserName((String) xmlMap.get("FromUserName"));
                    applicationContext.publishEvent(wechatMpSubscribeEvent);
                }
            }
        } catch (Exception e) {
            log.error("wechat procCallback error", e);
        }
    }




    @GetMapping("/getSignature")
    public Map<String, Object> getSignature(String url){
        Map<String, Object> reseltMap = new HashMap<>();
        if(StringUtils.isEmpty(url)){
            reseltMap.put("code",500);
            reseltMap.put("msg","url不能为空");
            return reseltMap;
        }
        String client_credential = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
        String body = HttpXmlClient.get(client_credential);
        JSONObject json = JSONObject.fromObject(body);
        String ACCESS_TOKEN = (String) json.get("access_token");
        String accessTokenURl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ACCESS_TOKEN+"&type=jsapi";
        String body1 = HttpXmlClient.get(accessTokenURl);
        String jsapi_ticket = (String) JSONObject.fromObject(body1).get("ticket");
        Map<String,String> data = new HashMap<>();
        // 注意 URL 一定要动态获取，不能 hardcode
        Map<String, String> ret = HttpXmlClient.sign(jsapi_ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            data.put(entry.getKey()+"",entry.getValue()+"");
        }
        data.put("appId",appId);
        reseltMap.put("code",200);
        reseltMap.put("msg","成功！");
        reseltMap.put("data",data);
        return reseltMap;
    };
}
